電商項目-查詢語句和sqlalchemy用法

概念

聚集索引:指索引項的排序方式和表中數據記錄排序方式一致的索引(這裏不懂先放着,一會舉例),每張表只能有一個聚集索引,聚集索引的葉子節點存儲了整個行數據。
輔助索引:輔助索引中索引的邏輯順序與磁盤上行的物理存儲順序不同,一個表中可以擁有多個非聚集索引。葉子節點並不包含行記錄的全部數據。葉子節點除了包含鍵值以外,還存儲了一個指向改行數據的聚集索引建的書籤。

一.查詢語句

1.想到查詢所有商品最近的一次分享記錄,並且當沒有最近的分享時候能生成空記錄

利用先排序後分組的思路,避免子查詢的排序失效,用了limit來保證;然後子查詢裏面放置

sql = '''select wcate.id, any_value(wcate.supplier_id), any_value(wcate.category_id),any_value(a.create_at), any_value(a.app_name), any_value(a.id)
        from wcate 
        left join (select * from user_cate_share  where user_cate_share.reseller_id=%s order by user_cate_share.id desc limit 1000) a
        on wcate.id = a.wcate_id
        where wcate.id in %s
        GROUP BY wcate.id'''

cursor.execute(sql, (reseller_id, wcate_id_list))
row = cursor.fetchone()
catalog_id, supplier_id = row['id'], row['any_value(wcate.supplier_id)']

2.查詢時間爲+5.5並且按照天分組,計算每天結果去重後的數量

select DATE_FORMAT(DATE_ADD(wcate.create_at, INTERVAL 5.5 hour),'%Y%m%d') as wcate_create_at, count(DISTINCT wcate.wcate_code), count(DISTINCT wsku.product_code), count(DISTINCT wsku.id)
from wsku
join wcate on wsku.wcate_id=wcate.id
GROUP BY  wcate_create_at
ORDER BY wcate_create_at desc

3.緩存池超過使用的範圍,連接超時

sqlalchemy.exc.TimeoutError: QueuePool limit of size 10 overflow 10 reached, connection timed out, timeout 10 (Background on this error at: http://sqlalche.me/e/3o7r)

出現這個錯的時候一般後端的表現爲有部分請求非常慢,或者大部分請求都非常慢,如果後端頻繁出現這個問題的時候,可以根據這兩種情況進行分析:
Flask-SQLAlchemy 默認給你的 session 是一個 scoped_session,是一個 ThreadLocal 的對象,在大部分情況下,一個線程裏拿到的都是同一個 session,你可以多次調用 db.session() 觀察其 id,當你 db.session.remove() 了一次後,db.session() 纔會拿到不一樣的 session。

二.sqlalchemy語法

1.批量插入數據sqlalchemy.orm.session

    insert_sql = text("""
        INSERT INTO
            reseller_behavior(`reseller_id`, login_at, session_time, click_times, cart_times, pay_times, 
            search_list,view_times,catalog_id, supplier_id,category_id,last_share_time,which_app)
        VALUES(
            :reseller_id,
            :login_at,
            :session_time,
            :click_times,
            :cart_times,
            :pay_times,
            :search_list,
            :view_times,
            :catalog_id,
            :supplier_id,
            :category_id,
            :last_share_time,
            :which_app
        )
    """) 

    wemore_oms_session.execute(insert_sql, insert_list)  #insert_list是一個字典的列表

2.返回值

select = db.session.query(Wcate).first()

<Wcate 4>  Wcate對象

select = db.session.query(Wcate.id).first()

(1001,)  需要解包

3.execute() 函數本身有接受sql語句參數位的,可以通過python自身的函數處理sql注入問題。

#寫法1
args = (id, type)
cur.execute('select id, type ,name from xl_bugs where id = %s and type = %s', args )

#寫法2
# And this is the named style:
cur.execute("select * from people where name_last=:who and age=:age", {"who": who, "age": age})

from sqlalchemy import text
sql = text('SELECT * from user_t WHERE username = :username;')
data = session.execute(sql, {'username':'test'}).fetchall()

用session(orm)執行,第二個參數是字典,用cursor(pymysql)執行,第二個參數是元組

4.orderby和limit同時使用,如果你需要確保無論帶不帶LIMIT都要以相同的順序返回,那麼你可以在ORDER BY中包含附加列,如id(自帶索引)

5. 如果你將LIMIT row_count子句與ORDER BY子句組合在一起使用的話,MySQL會在找到排序結果的第一個row_count行後立即停止排序,而不是對整個結果進行排序。     所以同時用的時候,order by字段不用索引。

6.limit 2000, 20。 1.掃描2020行,丟掉2000行,減少查詢的量,儘量通過主鍵覆蓋的的字段先排完序後,再查詢其他數據;2.通過記錄上次查詢的主鍵的最後一位id,先判斷id,只取20條, where MemberID >= (select MemberID from Member limit 100000,1)

7.Cursor,以元組的方式保存,DictCursor是以字典的形式保存
SSCursor和SSDictCursor流式遊標,這類遊標不會像上面使用的Cursor和DictCursor那樣,一次性返回所有的數據,流式遊標會陸陸續續一條一條得返回查詢數據,所以這類遊標適用於內存低、網絡帶寬小、數據量大的應用場景中。要配合cursor.fetchone()

8.多個表一起查詢,右鏈接不生效

select wcate.id, max(IFNULL(t.is_notify, 1)) from wcate
left join wsku on wsku.wcate_id = wcate.id
left join offer on offer.wsku_id = wsku.id
left join (SELECT reseller_notify.offer_id, reseller_notify.reseller_id, reseller_notify.is_notify from reseller_notify where reseller_notify.reseller_id = 1001 ) t
on t.offer_id = offer.id
where wcate.id in (1520, 1521)
GROUP BY wcate.id ;

9.Deadlock found when trying to get lock; try restarting transaction

通過查詢資料知道,對有索引的字段更新數據會用行級鎖,其他的時候是表級鎖;此處應該是用到行級鎖但是仍然死鎖,

ab -c 10 -n 10  -T 'application/json'  -H  'token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1Njc1MTk5NDEsImV4cCI6MTU3MDExMTk0MSwic291cmNlX3R5cGUiOjMsInVpZCI6MTEyOSwiZGV2aWNlX2lkIjo0NDQxNTUwMX0.nlUrilI99H9FpxDFnLTyu0_JLBzSN29j7p6CUqDIkmE' -s 120 -p /home/test/productcate.txt  https://test.thewemore.com/api/v1.0/product/productcate

通過ab大量跑復現,發現是orm修改和execute兩處修改,都未提交導致死鎖的。

行級鎖並不是直接鎖記錄,而是鎖索引,如果一條SQL語句用到了主鍵索引,mysql會鎖住主鍵索引;如果一條語句操作了非主鍵索引,mysql會先鎖住非主鍵索引,再鎖定主鍵索引。如果操作用到了主鍵索引會先在主鍵索引上加鎖,然後在其他索引上加鎖,否則加鎖順序相反

# case when

select  B.`userId`,SUM(B.`change`), B.`Atype` FROM  (select A.`userId`,A.`change`,
(case
when A.`type` =1  or A.`type`=5  then 1
when A.`type` =2  or A.`type`  then 3
else 2
end
)   `Atype1`
FROM `xc_ebike_user_wallet_record`  A ) B
GROUP BY B.`userId`, B.`Atype`

#多列變成多行

SELECT D.id, D.balance, D.recharge, D.present, C.change1, C.change2, C.change3 FROM xc_ebike_usrs_2 D
JOIN
(select  B.`userId`,SUM(B.`change1`),SUM(B.`change2`),SUM(B.`change3`)  FROM  (select A.`userId`,
IF(A.`type` =1  or A.`type`=5, A.`change`, 0) AS change1,
IF(A.`type` =3 or A.`type`=4 or A.`type`=6 or A.`type`=7 or A.`type`=8, A.`change`, 0) AS change2,
IF(A.`type` =2, A.`change`, 0) AS change3
FROM `xc_ebike_user_wallet_record`  A) B
GROUP BY B.`userId`) C
ON C.userId=D.id

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章